home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / tracker-4.13.lha / tracker / lookup.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-15  |  6.0 KB  |  266 lines

  1. /* lookup.c 
  2.     vi:ts=3 sw=3:
  3.  */
  4.  
  5. /* A simple database lookup.
  6.  * every entry in the database files is of the form: initial string value
  7.  * We just have to match the initial string, no separators required.
  8.  * Not that the specification just asks for a matching entry, not
  9.  * necessarily the first or the last.
  10.  */
  11. /* $Id: lookup.c,v 4.7 1995/02/08 13:14:56 espie Exp $ */
  12.  
  13. /* $Log: lookup.c,v $
  14.  * Revision 4.7  1995/02/08  13:14:56  espie
  15.  * *** empty log message ***
  16.  *
  17.  * Revision 4.7  1995/02/08  13:14:56  espie
  18.  * *** empty log message ***
  19.  *
  20.  * Revision 4.6  1995/02/01  20:41:45  espie
  21.  * Added color.
  22.  *
  23.  * Revision 4.6  1995/02/01  20:41:45  espie
  24.  * Added color.
  25.  *
  26.  * Revision 4.5  1995/02/01  16:39:04  espie
  27.  * Moved includes to defs.h
  28.  *
  29.  * Revision 4.5  1995/02/01  16:39:04  espie
  30.  * Moved includes to defs.h
  31.  *
  32.  * Revision 1.2  1992/07/22  14:50:25  espie
  33.  * open_file changed, so lookup had to change to incorporate paths as well.
  34.  */
  35.  
  36. #include "defs.h"
  37. #include "extern.h"
  38.  
  39. ID("$Id: lookup.c,v 4.7 1995/02/08 13:14:56 espie Exp $")
  40.  
  41. /* the lookup structure is PRIVATE */
  42.  
  43. #define HANDLE 0    /* a null type, for memory handling */
  44. #define FNAME 1     /* a filename, which has not yet been opened */
  45. #define FOPENED 2   /* a file, once opened */
  46. #define STRING 3    /* an already accounted for string */
  47.  
  48. struct lookup
  49.    {
  50.    int type;
  51.    union 
  52.       {
  53.       char *filename;
  54.       FILE *file;
  55.       char *string;
  56.       char *path;
  57.       } value;
  58.    struct lookup *next;
  59.    };
  60.  
  61. /***
  62.  *
  63.  * lookup memory handling 
  64.  *
  65.  ***/
  66.  
  67. /* link_lookup(base, new): link a new element inside the existing chain */
  68. LOCAL void link_lookup(handle, new)
  69. struct lookup *handle, *new;
  70.    {
  71.    new->next = handle->next;
  72.    handle->next = new;
  73.    }
  74.  
  75. LOCAL void set_lookup(handle, path)
  76. struct lookup *handle;
  77. char *path;
  78.    {
  79.    handle->type = HANDLE;
  80.    handle->value.path = path;
  81.    }
  82.  
  83. /* new = create_lookup(): create an empty element, 
  84.  * chain anchor or to be filled 
  85.  */
  86. struct lookup *create_lookup(path)
  87. char *path;
  88.    {
  89.    struct lookup *new;
  90.  
  91.    new = (struct lookup *)malloc(sizeof(struct lookup));
  92.    if (!new)
  93.       exit(10);
  94.    set_lookup(path);
  95.    new->next = NULL;
  96.    return new;
  97.    }
  98.  
  99. /* free_lookup(handle): free the whole chain. Note that filenames
  100.  * do not belong to us
  101.  */
  102. void free_lookup(handle)
  103. struct lookup *handle;
  104.    {
  105.    struct lookup *to_free;
  106.  
  107.    while(handle)
  108.       {
  109.       to_free = handle;
  110.       handle = handle->next;
  111.       switch(to_free->type)
  112.          {
  113.       case HANDLE:
  114.       case FNAME: /* filenames don't belong to you */
  115.          break;
  116.       case FOPENED:
  117.          close_file(to_free->value.file.fhandle, 
  118.             to_free->value.file.filetype);
  119.          break;
  120.       case STRING:
  121.          free(to_free->value.string);
  122.          break;
  123.          }
  124.       free(to_free);
  125.       }
  126.    }
  127.  
  128. /* add_lookup(handle, filename): add a new potential filename to the lookup
  129.  * handle
  130.  */
  131. void add_lookup(handle, filename)
  132. struct lookup *handle;
  133. char *filename;
  134.    {
  135.    struct lookup *new;
  136.  
  137.    new = create_lookup();
  138.    new->type = FNAME;
  139.    new->value.filename = filename;
  140.    link_lookup(handle, new);
  141.    }
  142.  
  143.  
  144. /* postfix = check_prefix(template, s):
  145.  * if s is a prefix of template, return the remaining part of template,
  146.  * else return NULL.
  147.  * Note difference between NULL result and empty postfix (pointer to NULL)
  148.  */
  149. static char *check_prefix(template, s)
  150. char *template;
  151. char *s;
  152.    {
  153.    for (; *s; template++, s++)
  154.       /* *s != 0 at that point */
  155.       if (*template != *s)
  156.          return NULL;
  157.    while(*template == ' ' || *template == '\t')
  158.       template++;
  159.    return template;
  160.    }
  161.  
  162. /* copy = create_copy(s): allocate memory and create a copy of string s.
  163.  * get rid of spurious \n at the end.
  164.  */
  165. static char *create_copy(s)
  166. char *s;
  167.    {
  168.    char *new;
  169.    int len;
  170.  
  171.    len = strlen(s);
  172.    while(s[len - 1] == '\n')
  173.       s[--len] = 0;
  174.    new = malloc(len + 1);
  175.    if (!new)
  176.       exit(10);
  177.    return strcpy(new, s);
  178.    }
  179.  
  180. #define BUFSIZE 1500
  181.  
  182. LOCAL char *internal_lookup();
  183.  
  184. /* postfix = lookup(handle, s): lookup string s in the database indexed by
  185.  * handle.
  186.  */
  187. char *lookup(handle, s)
  188. struct lookup *handle;
  189. char *s;
  190.    {
  191.       /* the internal handler also maintains a current path */
  192.    return internal_lookup(handle, s, NULL);
  193.    }
  194.  
  195.  
  196. LOCAL char *internal_lookup(handle, s, path)
  197. struct lookup *handle;
  198. char *s;
  199. char *path;
  200.    {
  201.    char *r;
  202.    static char buffer[BUFSIZE];
  203.    struct lookup *new;
  204.  
  205.    if (handle)
  206.       {
  207.       switch(handle->type)
  208.          {
  209.       case STRING:
  210.          r = check_string(handle->value.string, s);
  211.          if (r)
  212.             return r;
  213.          else
  214.             return internal_lookup(handle->next, s, path);
  215.       case HANDLE:
  216.          return internal_lookup(handle->next, s,
  217.             handle->value.path ? handle->value.path : path);
  218.       case FNAME:
  219.          r = internal_lookup(handle->next, s, path);
  220.          if (r)
  221.             return r;
  222.          else
  223.             {
  224.             if (handle->value.file = 
  225.                open_file(handle->value.filename, "r", path))
  226.                {
  227.                handle->type = FOPENED;
  228.                return internal_lookup(handle, s, path);
  229.                }
  230.             else
  231.                {
  232.                set_lookup(handle, NULL);
  233.                return NULL;
  234.                }
  235.             }
  236.       case FOPENED:
  237.          r = internal_lookup(handle->next, s, path);
  238.          if (r)
  239.             return r;
  240.          else
  241.             {
  242.             if (fgets(buffer, BUFSIZE, handle->value.file))
  243.                {
  244.                new = create_lookup(NULL);
  245.                new->type = STRING;
  246.                new->value.string = create_copy(buffer);
  247.                link_lookup(handle, new);
  248.                r = check_prefix(new->value.string, s);
  249.                if (r)
  250.                   return r;
  251.                else
  252.                   return internal_lookup(handle, s, path);
  253.                }
  254.             else
  255.                {
  256.                close_file(handle->value.file);
  257.                set_lookup(new, NULL);
  258.                }
  259.             }
  260.          }
  261.       }
  262.    else
  263.       return NULL;
  264.    }
  265.             
  266.